#!/usr/bin/env python
# -*- coding: utf-8; py-indent-offset:4 -*-
###############################################################################
#
# Copyright (C) 2015-2020 Daniel Rodriguez
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)


import collections

import backtrader as bt
from backtrader import Order, Position
from backtrader.utils.datehelper import *
import pandas as pd

"""
成交历史
"""


class Trades(bt.Analyzer):
    '''This analyzer reports the trades history occurred with each an every data in
    the system

    It looks at the order execution bits to create a ``Position`` starting from
    0 during each ``next`` cycle.

    The result is used during next to record the transactions

    Params:

      - headers (default: ``True``)

        Add an initial key to the dictionary holding the results with the names
        of the datas

        This analyzer was modeled to facilitate the integration with
        ``pyfolio`` and the header names are taken from the samples used for
        it::

          'date', 'amount', 'price', 'sid', 'symbol', 'value'
          - amount: 持仓大小
          - price: 持仓平均价格
          - value: 持仓权益

    Methods:

      - get_analysis

        Returns a dictionary with returns as values and the datetime points for
        each return as keys
    '''
    params = (
        ('headers', False),
        ('_pfheaders', ('symbol', 'opentime', 'closetime', 'hsize', 'hprice', 'hvalue', 'csize', 'cprice', 'cvalue',
                        'comm', 'pnl', 'pnlcomm', 'hlen')),
        ('csv', False),
        ('out', None),
        ('rounding', 6)
    )

    def start(self):
        super(Trades, self).start()
        self.rets["history"] = list()
        if self.p.headers:
            self.rets["history"].append(list(self.p._pfheaders[0:]))

    def notify_trade(self, trade: bt.Trade):
        if trade.status == trade.Closed:
            symbol = trade.data._name
            item = [
                symbol, date2str(trade.open_datetime()), date2str(trade.close_datetime()),
                trade.size, trade.price, trade.value, trade.closesize, trade.closeprice, trade.closevalue,
                trade.commission, trade.pnl, trade.pnlcomm, trade.barlen
            ]
            self.rets["history"].append(item)

    def stop(self):
        if self.p.csv and self.p.out:
            params = self.strategy.p.__dict__.copy()
            params['asset'] = self.data._name
            if self.p.out.startswith("f"):
                out = eval(self.p.out, params)
            else:
                out = self.p.out
            import os
            if not os.path.exists(out):
                os.makedirs(out)

            fpath = os.path.join(out, "trades.csv")
            self.to_dataframe().to_csv(fpath, index=False)

    def to_dataframe(self):
        cols = self.p._pfheaders
        _skip_headers = self.p.headers
        if _skip_headers:
            data = self.rets["history"][1:]
        else:
            data = self.rets["history"]

        df = pd.DataFrame(columns=cols, data=data)
        df = df.round(decimals=self.p.rounding)
        return df


